<template>
  <div>
    <div class="top-panel">
      <el-card>
        <el-form
          ref="searchForm"
          :model="searchForm"
          label-width="80px"
          label-position="right"
        >
          <el-row :gutter="10">
            <el-col :span="5">
              <el-form-item label="任务名称" size="small">
                <el-input
                  class="password-input"
                  v-model="searchForm.taskNameFuzzy"
                  clearable
                  placeholder="支持模糊搜索"
                  @keyup.enter.native="loadDataList"
                >
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="7">
              <el-form-item
                label="任务执行类名"
                size="small"
                label-width="100px"
              >
                <el-input
                  class="password-input"
                  v-model="searchForm.classzFuzzy"
                  clearable
                  placeholder="支持模糊搜索"
                  @keyup.enter.native="loadDataList"
                >
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="7">
              <el-form-item
                label="任务执行方法名"
                size="small"
                label-width="110px"
              >
                <el-input
                  class="password-input"
                  v-model="searchForm.methodFuzzy"
                  clearable
                  placeholder="支持模糊搜索"
                  @keyup.enter.native="loadDataList"
                >
                </el-input>
              </el-form-item>
            </el-col>
            <el-col
              :span="4"
              :style="{ paddingLeft: '10px', 'padding-top': '3px' }"
            >
              <el-button type="success" size="mini" @click="loadDataList()"
                >查询</el-button
              >
              <el-button
                v-has="permissionCode.edit"
                type="primary"
                size="mini"
                @click="showEdit('add')"
                >新增任务</el-button
              >
            </el-col>
          </el-row>
        </el-form>
      </el-card>
    </div>
    <el-card>
      <Table
        :columns="columns"
        :fetch="loadDataList"
        :dataSource="tableData"
        :options="tableOptions"
      >
      </Table>
    </el-card>
    <Dialog
      :title="editDialogInfo.title"
      :buttons="editDialogInfo.buttons"
      :visible="editDialogInfo.show"
      @close="editDialogInfo.show = false"
      :width="'600px'"
    >
      <el-alert
        title="执行任务的方法不要捕获异常，将异常抛出，便于任务收集错误"
        type="warning"
        show-icon
        :closable="false"
      >
      </el-alert>
      <el-form
        :style="{ 'margin-top': '10px' }"
        ref="editForm"
        :model="formData"
        :rules="rules"
        label-width="140px"
      >
        <el-form-item label="任务名称" prop="taskName" size="small">
          <el-input
            :maxLength="50"
            v-model="formData.taskName"
            placeholder="请输入任务名称"
          />
        </el-form-item>
        <el-form-item label="任务执行类名" prop="classz" size="small">
          <el-input
            :maxLength="200"
            v-model="formData.classz"
            placeholder="请输入完整的类名或者springBean名称"
          />
        </el-form-item>
        <el-form-item size="small" label="任务执行方法名" prop="method">
          <el-input
            :maxLength="200"
            v-model="formData.method"
            placeholder="请输入任务执行方法名 eg: resetCache"
          />
        </el-form-item>
        <el-form-item size="small" label="任务执行时间" prop="cron">
          <el-input
            :maxLength="20"
            v-model="formData.cron"
            placeholder="请输入cron表达式"
            :style="{ width: '350px' }"
          />
          <el-popover
            placement="right"
            width="610"
            trigger="click"
            title="corn表达式示例"
          >
            <el-table :data="cronExample" height="300">
              <el-table-column
                width="160"
                property="cron"
                label="cron表达式"
              ></el-table-column>
              <el-table-column
                width="450"
                property="desc"
                label="描述"
              ></el-table-column>
            </el-table>
            <el-button
              slot="reference"
              type="text"
              :style="{ 'margin-left': '5px' }"
              >如何设置？</el-button
            >
          </el-popover>
        </el-form-item>
        <el-form-item label="方法类型" size="small" prop="methodType">
          <el-radio v-model="formData.methodType" :label="0">无参方法</el-radio>
          <el-radio v-model="formData.methodType" :label="1">有参方法</el-radio>
        </el-form-item>
        <el-form-item
          label="执行参数"
          size="small"
          prop="params"
          v-if="formData.methodType == 1"
        >
          <el-input
            :maxLength="500"
            v-model="formData.params"
            type="textarea"
            :rows="4"
            placeholder="建议使用json格式，具体任务方法配合此参数使用"
          />
        </el-form-item>
        <el-form-item
          label="是否记录执行日志"
          size="small"
          prop="recordRunLogType"
        >
          <el-radio v-model="formData.recordRunLogType" :label="0"
            >不记录</el-radio
          >
          <el-radio v-model="formData.recordRunLogType" :label="1"
            >记录</el-radio
          >
        </el-form-item>
        <el-form-item label="任务描述" size="small" prop="taskDesc">
          <el-input
            :maxLength="500"
            v-model="formData.taskDesc"
            type="textarea"
            :rows="4"
            placeholder="请输入任务描述"
          />
        </el-form-item>
        <el-form-item label="立即执行" size="small" prop="immediatelyRun">
          <el-checkbox
            v-model="formData.immediatelyRun"
            true-label="true"
          ></el-checkbox>
        </el-form-item>
      </el-form>
    </Dialog>

    <Dialog
      ref="showLogDialog"
      :title="showLogDialog.title"
      :buttons="showLogDialog.buttons"
      :visible="showLogDialog.show"
      @close="showLogDialog.show = false"
      :showCancel="false"
      width="45%"
    >
      <el-form
        ref="searchForm"
        :model="searchForm"
        label-width="80px"
        label-position="right"
      >
        <el-row :gutter="10">
          <el-col :span="10">
            <el-form-item label="执行日期" size="small">
              <el-date-picker
                :style="{ width: '100%' }"
                v-model="searchLogForm.dateRang"
                type="daterange"
                range-separator="至"
                value-format="yyyy-MM-dd"
              >
              </el-date-picker>
            </el-form-item>
          </el-col>
          <el-col
            :span="4"
            :style="{ paddingLeft: '10px', 'padding-top': '3px' }"
          >
            <el-button type="success" size="mini" @click="loadLogDataList()"
              >查询</el-button
            >
          </el-col>
        </el-row>
      </el-form>
      <Table
        :columns="logColumns"
        :fetch="loadLogDataList"
        :dataSource="logTableData"
        :options="logTableOptions"
        :initFetch="false"
      >
      </Table>
    </Dialog>

    <Dialog
      ref="showLogErrorDialog"
      :title="showLogErrorDialog.title"
      :buttons="showLogErrorDialog.buttons"
      :visible="showLogErrorDialog.show"
      @close="showLogErrorDialog.show = false"
      :showCancel="false"
      width="40%"
    >
      <div v-html="errorInfo"></div>
    </Dialog>
  </div>
</template>
<script>
export default {
  data() {
    let validateRePass = (rule, value, callback) => {
      if (value !== this.formData.password) {
        callback(new Error(rule.message))
      } else {
        callback()
      }
    }

    return {
      permissionCode: {
        edit: 'task_edit',
        del: 'task_del',
        taskLog: 'task_log',
      },
      cronExample: [
        { cron: '0/10 * * * * ?', desc: '每10秒触发' },
        { cron: '0 0/3 * * * ?', desc: '每3分钟触发' },
        { cron: '0 0 12 * * ?', desc: '每天中午12点触发' },
        { cron: '0 15 10 ? * *', desc: '每天上午10:15触发' },
        { cron: '0 15 10 * * ?', desc: '2005 2005年的每天上午10:15触发' },
        { cron: '0 15 10 * * ? *', desc: '每天上午10:15触发' },
        {
          cron: '0 * 14 * * ?',
          desc: '在每天下午2点到下午2:59期间的每1分钟触发',
        },
        {
          cron: '0 0/5 14 * * ?',
          desc: '在每天下午2点到下午2:55期间的每5分钟触发',
        },
        {
          cron: '0 0/5 14,18 * * ?',
          desc: '在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发',
        },
        {
          cron: '0 0-5 14 * * ?',
          desc: '在每天下午2点到下午2:05期间的每1分钟触发',
        },
        {
          cron: '0 10,44 14 ? 3 WED',
          desc: '每年三月的星期三的下午2:10和2:44触发',
        },
        { cron: '0 15 10 ? * MON-FRI	', desc: '周一至周五的上午10:15触发' },
        { cron: '0 15 10 15 * ?', desc: '每月15日上午10:15触发' },
        { cron: '0 15 10 L * ?', desc: '每月最后一日的上午10:15触发' },
        { cron: '0 15 10 ? * 6L', desc: '每月的最后一个星期五上午10:15触发' },
        {
          cron: '0 15 10 ? * 6L ',
          desc: '2002-2005	2002年至2005年的每月的最后一个星期五上午10:15触发',
        },
        { cron: '0 15 10 ? * 6#3', desc: '每月的第三个星期五上午10:15触发' },
        { cron: '0 0 06,18 * * ?', desc: '在每天上午6点和下午6点触发' },
        { cron: '0 30 5 * * ? *', desc: '在每天上午5:30触发' },
      ],
      tableData: {},
      tableOptions: {
        topHeight: 58,
      },
      columns: [
        {
          label: '任务ID',
          prop: 'taskId',
          width: 70,
        },
        {
          label: '任务名称',
          prop: 'taskName',
          width: 200,
        },
        {
          label: '执行时间cron',
          prop: 'cron',
          width: 400,
          render: (row, index) => {
            return (
              <div>
                <div>执行时间cron：{row.cron}</div>
                <div>任务执行类名：{row.classz}</div>
                <div>任务执行方法名：{row.method}</div>
                <div>
                  任务执行方法类型：
                  {row.methodType == 0 ? '无参方法' : '有参方法'}
                </div>
                <div>
                  是否记录执行日志：
                  {row.recordRunLogType == 0 ? '不记录' : '记录'}
                </div>
              </div>
            )
          },
        },
        {
          label: '执行参数',
          prop: 'params',
        },
        {
          label: '任务描述',
          prop: 'taskDesc',
          width: 200,
        },
        {
          label: '创建时间',
          prop: 'createTime',
          width: 200,
        },
        {
          label: '状态',
          prop: 'status',
          width: 80,
          render: (row, index) => {
            return (
              <div class="table-list-op-btns">
                {row.status == 0 ? (
                  <span style="color:red">暂停</span>
                ) : (
                  <span style="color:green">开启</span>
                )}
              </div>
            )
          },
        },
        {
          label: '操作',
          prop: 'operation',
          width: 330,
          fixed: 'right',
          render: (row, index) => {
            return (
              <div class="table-list-op-btns">
                <span v-has={this.permissionCode.edit}>
                  <a
                    href="javascript:void(0)"
                    onClick={() => this.showEdit('edit', row)}
                  >
                    修改
                  </a>
                </span>
                <span v-has={this.permissionCode.del}>
                  <a
                    href="javascript:void(0)"
                    onClick={() => this.delTask(row)}
                  >
                    删除
                  </a>
                </span>
                <span v-has={this.permissionCode.edit}>
                  <a
                    href="javascript:void(0)"
                    onClick={() => this.immediatelyRun(row)}
                  >
                    立即执行
                  </a>
                </span>
                <span v-has={this.permissionCode.edit}>
                  <a
                    href="javascript:void(0)"
                    onClick={() => this.changeStatus(row)}
                  >
                    {row.status == 0 ? '开启' : '暂停'}
                  </a>
                </span>
                <span v-has={this.permissionCode.taskLog}>
                  <a
                    href="javascript:void(0)"
                    onClick={() => this.showLog(row)}
                  >
                    执行日志
                  </a>
                </span>
              </div>
            )
          },
        },
      ],

      logTableData: {},
      logTableOptions: {
        height: 500,
      },
      logColumns: [
        {
          label: '开始时间',
          prop: 'startTime',
          width: 200,
        },
        {
          label: '结束时间',
          prop: 'endTime',
          width: 200,
        },
        {
          label: '耗时',
          prop: 'runTime',
          width: 100,
        },
        {
          label: '执行结果',
          prop: 'result',
          width: 100,
          render: (row, index) => {
            return (
              <div>
                {row.result == 1 ? (
                  <div style="color:green">成功</div>
                ) : (
                  <div style="color:red">失败</div>
                )}
              </div>
            )
          },
        },
        {
          label: '操作',
          prop: 'op',
          render: (row, index) => {
            return (
              <div>
                {row.result !== 1 ? (
                  <el-button
                    type="danger"
                    size="mini"
                    onClick={() => this.showErrorInfo(row)}
                  >
                    查看错误信息
                  </el-button>
                ) : null}
              </div>
            )
          },
        },
      ],
      api: {
        loadDataList: '/task/loadTaskList',
        saveTask: '/task/saveTask',
        delTask: '/task/delTask',
        immediatelyRun: '/task/immediatelyRunTask',
        updateStatus: '/task/suspendAndStartTask',
        loadLogList: '/task/loadRunTaskLog',
      },
      editDialogInfo: {
        title: '新增账号',
        buttons: [
          {
            type: 'primary',
            text: '确定',
            click: (e) => {
              this.submitForm(e)
            },
          },
        ],
        show: false,
      },
      showLogDialog: {
        title: '执行日志',
        buttons: [
          {
            type: 'primary',
            text: '关闭',
            click: (e) => {
              this.showLogDialog.show = false
            },
          },
        ],
        show: false,
      },

      showLogErrorDialog: {
        title: '错误信息',
        buttons: [
          {
            type: 'primary',
            text: '关闭',
            click: (e) => {
              this.showLogErrorDialog.show = false
            },
          },
        ],
        show: false,
      },

      formData: {
        roles: [],
      },
      rules: {
        taskName: [{ required: true, message: '请输入任务名称' }],
        classz: [{ required: true, message: '请输入任务执行类名' }],
        method: [{ required: true, message: '请输入任务执行方法名' }],
        cron: [{ required: true, message: '请输入任务执行时间' }],
        methodType: [{ required: true, message: '请选择方法类型' }],
        params: [{ required: true, message: '请输入执行参数' }],
        recordRunLogType: [
          { required: true, message: '请选择是否记录执行日志' },
        ],
      },
      searchForm: {},
      searchLogForm: {},
      errorInfo: '',
    }
  },
  methods: {
    async loadDataList() {
      let params = {
        pageNo: this.tableData.pageNo,
        pageSize: this.tableData.pageSize,
      }
      Object.assign(params, this.searchForm)

      let result = await this.Request({
        url: this.api.loadDataList,
        params: params,
      })
      this.tableData = result
    },

    //展示表单
    async showEdit(type, data) {
      // this.$refs.editForm.resetFields()
      this.editDialogInfo.show = true
      this.$nextTick(async () => {
        if (this.$refs['editForm'] !== undefined) {
          this.$refs['editForm'].resetFields()
        }
        if (type === 'add') {
          this.editDialogInfo.edit = false
          this.editDialogInfo.title = '新增定时任务'
          this.formData = {
            immediatelyRun: false,
          }
        } else {
          this.editDialogInfo.edit = true
          this.editDialogInfo.title = '修改定时任务'
          let editData = Object.assign({}, data)
          delete editData.createTime
          editData.immediatelyRun = false
          this.formData = editData
        }
      })
    },
    //提交表单
    async submitForm(e) {
      e.preventDefault()
      this.$refs.editForm.validate(async (valid) => {
        if (!valid) {
          return false
        }
        let params = {}
        Object.assign(params, this.formData)
        await this.Request({
          url: this.api.saveTask,
          params: params,
        })
        this.editDialogInfo.show = false
        this.$message.success('保存成功')
        this.loadDataList()
      })
    },
    //删除
    delTask(data) {
      this.$confirm(`确认要删除【${data.taskName}】吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          await this.Request({
            url: this.api.delTask,
            params: {
              taskId: data.taskId,
            },
          })
          this.$message.success('删除成功')
          this.loadDataList()
        })
        .catch(() => {})
    },
    //立即执行
    immediatelyRun(data) {
      this.$confirm(`确认要立即执行【${data.taskName}】吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          await this.Request({
            url: this.api.immediatelyRun,
            params: {
              taskId: data.taskId,
            },
          })
          this.$message.success('操作成功')
          this.loadDataList()
        })
        .catch(() => {})
    },

    //启用，暂停
    changeStatus(data) {
      let status = data.status == 0 ? 1 : 0
      let info = status == 0 ? '暂停' : '开启'
      this.$confirm(`确认要【${info}】【${data.taskName}】吗？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          await this.Request({
            url: this.api.updateStatus,
            params: {
              taskId: data.taskId,
              opStatus: status,
            },
          })
          this.$message.success('操作成功')
          this.loadDataList()
        })
        .catch(() => {})
    },

    //修改密码
    async showLog(data) {
      this.showLogDialog.show = true
      this.searchLogForm.taskId = data.taskId
      this.loadLogDataList()
    },

    async loadLogDataList() {
      let params = {
        pageNo: this.logTableData.pageNo,
        pageSize: this.logTableData.pageSize,
      }
      Object.assign(params, this.searchLogForm)

      if (params.dateRang) {
        params.startTimeStart = params.dateRang[0]
        params.startTimeEnd = params.dateRang[1]
        delete params.dateRang
      }

      let result = await this.Request({
        url: this.api.loadLogList,
        params: params,
      })
      this.logTableData = result
    },
    showErrorInfo(data) {
      this.showLogErrorDialog.show = true
      let errorInfo = data.errorInfo
      errorInfo = errorInfo.replace(new RegExp('\r\n', 'gm'), '<br/>')
      errorInfo = errorInfo.replace(
        new RegExp('\t', 'gm'),
        '&nbsp;&nbsp;&nbsp;&nbsp;'
      )
      this.errorInfo = errorInfo
    },
  },

  created() {},
}
</script>
<style lang="less" scoped>
.check-span-item {
  float: left;
  width: 30%;
  line-height: 20px;
}
</style>
